﻿// Copyright: 2012
// Author: Minh Vu - YoungJ
// File: XmlAction.cs - WindowsPhoneRssReader - WindowsPhoneRssReader
// Time: 9:12 PM 05/08/2012

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Xml.Linq;
using WindowsPhoneRssReader.Models;

namespace WindowsPhoneRssReader.Utils
{
    public class XmlAction
    {
        private const string _fileSource = "data.xml";
        public static bool SaveFeedsData(Feed feed)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    XDocument xdoc;
                    var eFeed = new XElement("feed", new XAttribute("id", feed.Id), new XAttribute("title", feed.FeedName), new XAttribute("url", feed.FeedUrl.UrlEncode()));
                    if (!storageFile.FileExists(_fileSource))
                    {
                        // create xml and save to xml
                        using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Create, storageFile))
                        {
                            xdoc = new XDocument(new XDeclaration("1.0", "utf-8", ""), new XElement("root", eFeed));
                            xdoc.Save(stream);
                            return true;
                        }
                    }

                    // load data from xml
                    using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    var root = xdoc.Element("root");
                    if (root == null) return false;
                    if (root.ToString().Equals("<root />"))
                    {
                        root.Add(eFeed);
                    }
                    else
                    {
                        var rsses = root.Descendants("feed");
                        var last = rsses.Last();
                        last.AddAfterSelf(eFeed);
                    }
                    using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }

                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine("Save feed: " + exception.Message);
                return false;
            }
        }

        public static IEnumerable<Feed> ReadFeedsData()
        {
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!storageFile.FileExists(_fileSource)) return null;
                using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Open, storageFile))
                {
                    try
                    {
                        var xdoc = XDocument.Load(stream);
                        var root = xdoc.Element("root");
                        if (root == null) return null;
                        var result = from r in root.Descendants("feed")
                                     select new Feed
                                     {
                                         Id = Convert.ToInt16(r.GetAttributeValue("id")),
                                         FeedName = r.GetAttributeValue("title"),
                                         FeedUrl = r.GetAttributeValue("url").UrlDecode()
                                         //ParentModel = rssReader
                                     };
                        return result;
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Read: " + ex.Message);
                        return null;
                    }

                }
            }
        }

        public static bool DeleteFeedData(int feedId)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!storageFile.FileExists(_fileSource)) return false;
                    XDocument xdoc;
                    using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    var root = xdoc.Element("root");
                    if (root == null) return false;

                    var eFeed = root.Descendants("feed")
                        .FirstOrDefault(
                            c => c.GetAttributeValue("id").Equals(feedId.ToString(CultureInfo.InvariantCulture)));
                    if (eFeed == null) return false;
                    eFeed.Remove();

                    using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine("Delete feed: " + exception.Message);
                return false;
            }
        }

        public static int NextId()
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!storageFile.FileExists(_fileSource)) return 1;

                    using (var stream = new IsolatedStorageFileStream(_fileSource, FileMode.Open, storageFile))
                    {
                        var xdoc = XDocument.Load(stream);

                        var root = xdoc.Element("root");
                        if (root == null || root.ToString().Equals("<root />")) return 1;

                        var rsses = root.Descendants("feed");
                        var last = rsses.Last();

                        var nextId = Convert.ToInt16(last.GetAttributeValue("id")) + 1;
                        return nextId;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("NextId: " + ex.Message);
                return -1;
            }

        }


        public static bool SaveFeed(Feed feed)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    var fileFeed = feed.Id + ".xml";
                    var efeedItems = new XElement("items", feed.FeedItems.Select(
                        item => new XElement("item", new XElement("title", item.Title),
                                             new XElement("description", item.Description),
                                             new XElement("link", item.Url),
                                             new XElement("pubDate", item.DatePublished),
                                             new XElement("favourite", item.Favourite),
                                             new XElement("read", item.Read))));
                    var efeed = new XElement("channel", efeedItems);
                    if (storageFile.FileExists(fileFeed))
                    {
                        storageFile.DeleteFile(fileFeed);
                    }

                    using (var stream = new IsolatedStorageFileStream(fileFeed, FileMode.Create, storageFile))
                    {
                        var xdoc = new XDocument(new XDeclaration("1.0", "utf-8", ""),
                                                 new XElement("rss", new XAttribute("version", "2.0"), efeed));
                        xdoc.Save(stream);
                        return true;
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine("Save feed: " + exception.Message);
            }
            return false;
        }

        public static string ReadFeed(int feedId)
        {
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                var fileFeed = feedId + ".xml";
                if (!storageFile.FileExists(fileFeed)) return null;
                using (var stream = new IsolatedStorageFileStream(fileFeed, FileMode.Open, storageFile))
                {
                    return XDocument.Load(stream).ToString();
                }
            }
        }

        public static void DeleteFeed(int feedId)
        {
            using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                var fileFeed = feedId + ".xml";
                if (storageFile.FileExists(fileFeed))
                    storageFile.DeleteFile(fileFeed);
            }
        }

        public static IEnumerable<FeedItem> GetFeedItems(int feedId)
        {
            var xml = ReadFeed(feedId);
            if (string.IsNullOrEmpty(xml)) return null;
            var rssFeed = XElement.Parse(xml);
            var items = from item in rssFeed.Descendants("item")
                        select new FeedItem
                        {
                            Title = item.GetValue("title"),
                            Description = item.GetDescription(),
                            Url = item.GetValue("link"),
                            DatePublished = item.GetValue("pubDate").ConvertToDateTime(),
                            Read =
                                !string.IsNullOrEmpty(item.GetValue("read")) &&
                                bool.Parse(item.GetValue("read")),
                            Favourite =
                            !string.IsNullOrEmpty(item.GetValue("favourite")) &&
                            bool.Parse(item.GetValue("favourite"))
                        };
            return items;
        }

        public static void UpdateReadFeedItem(FeedItem feedItem)
        {
            UpdateFeedItem(feedItem, "read", feedItem.Read);
        }
        public static void UpdateFavouriteFeedItem(FeedItem feedItem)
        {
            UpdateFeedItem(feedItem, "favourite", feedItem.Favourite);
        }



        private static void UpdateFeedItem(FeedItem feedItem, string name, object value)
        {
            try
            {
                using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    var fileFeed = feedItem.ParentFeed.Id + ".xml";
                    if (!storageFile.FileExists(fileFeed)) return;
                    XDocument xdoc;
                    using (var stream = new IsolatedStorageFileStream(fileFeed, FileMode.Open, storageFile))
                    {
                        xdoc = XDocument.Load(stream);
                    }
                    var efeedItem =
                        xdoc.Descendants("item").FirstOrDefault(
                            item => ((string)item.Element("link")).Equals(feedItem.Url));
                    if (efeedItem == null) return;
                    efeedItem.SetElementValue(name, value);

                    using (var stream = new IsolatedStorageFileStream(fileFeed, FileMode.Create, storageFile))
                    {
                        xdoc.Save(stream);

                        Debug.WriteLine(string.Format("{0} - {1} - {2}", feedItem.Title, name, value));
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine("Update read and favourite feed item: " + exception.Message);
            }
        }
    }
}